//
//  File.cpp
//  Prism
//
//  Created by Bas du Pre on 20-05-11.
//  Copyright 2011 UU. All rights reserved.
//

#include "global.h"
#include "File.h"

#include <sys/stat.h>

using namespace Prism;

File::File() {
    file = new std::fstream;
    _isOpen = false;
    _mode = File::In | File::Out;
}

File::File(File& file) {
    this->_filename = file._filename;
    this->file = file.file;
    this->_isOpen = file._isOpen;
    this->_mode = file._mode;
}

File::File(String filename) {
    // NOTE TO EVERYONE BREAKING HERE BECAUSE OF FILE DOES NOT EXIST:
    // it is possible your game will still work like expected because Cocos2D or
    // other engines try their best to look for the file. 
    // Prism is designed to work with absolute paths. If you want to know where
    // your resources are located, please take a look at File::resourcesPath().
    PRISM_ASSERT(File::exists(filename), "The file '%_' does not exist.", &filename);
    file = new std::fstream;
    this->_isOpen = false;
    open(filename);
}

File::File(String filename, Mode mode) {
    // NOTE TO EVERYONE BREAKING HERE BECAUSE OF FILE DOES NOT EXIST:
    // see previous constructor
    PRISM_ASSERT(File::exists(filename), "The file '%_' does not exist.", &filename);
    file = new std::fstream;
    this->_isOpen = false;
    open(filename, mode);
}

File & File::operator= (File &other)
{
    if (this != &other) // protect against invalid self-assignment
    {
        close();
        this->_filename = other._filename;
        this->file = other.file;
        this->_isOpen = other._isOpen;
        this->_mode = other._mode;
    }
    
    return *this;
}

File & File::operator= (const File &other)
{
    if (this != &other) // protect against invalid self-assignment
    {
        close();
        this->_filename = other._filename;
        this->file = other.file;
        this->_isOpen = other._isOpen;
        this->_mode = other._mode;
    }
    
    return *this;
}

File & File::operator= (File *other)
{
    if (this != other) // protect against invalid self-assignment
    {
        close();
        this->_filename = other->_filename;
        this->file = other->file;
        this->_isOpen = other->_isOpen;
        this->_mode = other->_mode;
    }
    
    return *this;
}


File::~File() {
    close();
    delete file;
}

void File::open(Prism::String filename) {
    return open(filename, File::In | File::Out);
}

void File::open(Prism::String filename, Mode mode) {
    close();
    _filename = filename;
    _mode = mode;
    _isOpen = false;
} 

void File::openForReadWrite() {
    if (_isOpen) return;
    file->open(_filename);
        
    _isOpen = file->is_open();
}

void File::close() {
    file->close();
    _filename = "";
}

void File::write(String data) {
    openForReadWrite();
    *file << data.c_str();
}

void File::writeLine(Prism::String line) {
    openForReadWrite();
    *file << line.c_str() << std::endl;
}

bool File::exists(String location) {
    struct stat stFileInfo; 
    bool blnReturn; 
    int intStat; 
    
    intStat = stat(location, &stFileInfo); 
    if(intStat == 0) { 
        blnReturn = true; 
    } else { 
        blnReturn = false; 
    } 
    
    return blnReturn;
}

bool File::fileExists(String filename) {
    ///\todo WINDOWS 
#if !PRISM_OS_WIN
	struct stat stFileInfo; 
    bool blnReturn; 
    int intStat; 
    
    intStat = stat(filename, &stFileInfo); 
    if(intStat == 0 && S_ISDIR(stFileInfo.st_mode)) { 
        blnReturn = true; 
    } else { 
        blnReturn = false; 
    } 
    
    return blnReturn;
#else
	return exists(filename);
#endif
}

bool File::dirExists(String dirname) {
#if !PRISM_OS_WIN
    struct stat stFileInfo; 
    bool blnReturn; 
    int intStat; 
    
    intStat = stat(dirname, &stFileInfo); 
    if(intStat == 0 && !S_ISDIR(stFileInfo.st_mode)) { 
        blnReturn = true; 
    } else { 
        blnReturn = false; 
    } 
    
    return blnReturn;
#else
	return exists(dirname);
#endif
}

String File::filename() const {
    return String(_filename);
}

String File::basename() const {
    String basename = filename();
    if (basename.find_last_of(File::dirSeparators) != -1) {
        basename = basename.substr(basename.find_last_of(File::dirSeparators) + 1);
    }
    return basename;
}

String File::dirname() const {
    String dirname = filename();
    if (dirname.find_last_of(File::dirSeparators) != -1) {
        dirname = dirname.substr(0, dirname.find_last_of(File::dirSeparators));
        return dirname;
    } else {
        return "";
    }
}

String File::resourcesPath() {
    return native_getResourcesPath();
}

String File::toString() {
    String b = basename();
    return String::fromFormat("[File filename=\"%_\"]", &b);
}

#if PRISM_OS_WIN
const String File::dirSeparators = "\\/";
#else
const String File::dirSeparators = "/";
#endif


